//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//	scantask.c
//		SCAN module
//	history :
//
//	Description:
//		Perform scan process.
//
//	Import msg:	SCANMSG_SCAN_REQ		(from SME)
//				SCANMSG_BEACON			(from RX)
//				SCANMSG_PROBE_RESPONSE	(from RX)
//				SCANMSG_ENABLE_BGSCAN	()
//	Export msg:	SMEMSG_SCAN_CFM
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "os_common.h"

//=================== Subroutine of SCAN Module
STATIC void vScanProc_ActiveNextChannel(PWB32_ADAPTER Adapter);
void vScanTimerStart(PWB32_ADAPTER Adapter, int timeout_value);
void vScanTimerStop(PWB32_ADAPTER Adapter);
void ScanTimerHandler_1a(IN	PVOID Data);
void ScanTimerHandler(IN	PVOID			SystemSpecific1,
							 IN PWB32_ADAPTER 	Adapter,
							 IN	PVOID			SystemSpecific2,
							 IN	PVOID			SystemSpecific3);
USHORT wRetrieveInformation(PWB32_ADAPTER Adapter, USHORT index, psRXDATA psRxFrame);
void StartIbssCheck(PWB32_ADAPTER Adapter, USHORT wBssIdx);

//=================== Action Function of SCAN Module
STATIC void vScanProc_ScanRequest(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_ProbeDelay_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_Min_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_Max_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_Cfm(PWB32_ADAPTER Adapter);
void vScanProc_StartIBSSCfm(PWB32_ADAPTER, USHORT);
STATIC void vScanProc_Passive_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_StopScan(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_RcvProbeRsp(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vScanProc_RcvBeacon(PWB32_ADAPTER Adapter, K_MSG* psMsg);
//Never used nowdays
//STATIC void vScanProc_TxProbeFail(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vStart_BgScanTimer(PWB32_ADAPTER Adapter, K_MSG* psMsg);
STATIC void vStart_BgScan(PWB32_ADAPTER Adapter, K_MSG* psMsg);

//========== Define the state machine table of SCAN module =================
static K_TRANS asScanInActive[] =
{
	{SCANMSG_SCAN_REQ,			vScanProc_ScanRequest			},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asWaitProbeDelay[] =
{
	{SCANMSG_BEACON,			vScanProc_RcvBeacon				},//??
	{SCANMSG_PROBE_RESPONSE,	vScanProc_RcvProbeRsp			},//??
	{SCANMSG_TIMEOUT,			vScanProc_ProbeDelay_Timeout	},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asWaitResponseMin[] =
{
	{SCANMSG_BEACON,			vScanProc_RcvBeacon				},
	{SCANMSG_PROBE_RESPONSE,	vScanProc_RcvProbeRsp			},
	{SCANMSG_TIMEOUT,			vScanProc_Min_Timeout			},
	//{SCANMSG_TXPROBE_FAIL,		vScanProc_TxProbeFail			},
	{SCANMSG_STOP_SCAN,			vScanProc_StopScan				},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asWaitResponseMaxActive[] =
{
	{SCANMSG_BEACON,			vScanProc_RcvBeacon				},
	{SCANMSG_PROBE_RESPONSE,	vScanProc_RcvProbeRsp			},
	{SCANMSG_TIMEOUT,			vScanProc_Max_Timeout			},
	{SCANMSG_STOP_SCAN,			vScanProc_StopScan				},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asWaitBeaconMaxPassive[] =
{
	{SCANMSG_BEACON,			vScanProc_RcvBeacon				},
	{SCANMSG_TIMEOUT,			vScanProc_Passive_Timeout		},
	{SCANMSG_STOP_SCAN,			vScanProc_StopScan				},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asScanComplete[] =
{
	{SCANMSG_BEACON,			vScanProc_RcvBeacon				},
	{SCANMSG_PROBE_RESPONSE,	vScanProc_RcvProbeRsp			},
	{SCANMSG_SCAN_REQ,			vStart_BgScan					},//request from SME
	{SCANMSG_ENABLE_BGSCAN,		vStart_BgScanTimer				},
	{SCANMSG_TIMEOUT,			vStart_BgScan					},//psSCAN->boBgScan == TRUE
	{K_NULL_MSG,				vProc_Null						}
};

//========= SCAN State Transition Table ==============================
static const K_TRANS* psScanTransTable[] =
{
	asScanInActive,
	asWaitProbeDelay,
	asWaitResponseMin,
	asWaitResponseMaxActive,
	asWaitBeaconMaxPassive,
	asScanComplete
};

//=========================================================================
//      Subroutine of SCAN Module 
//=========================================================================
void Scan_Init(PWB32_ADAPTER Adapter)
{
	Scan_ResetPara(Adapter);
	//Initilize scan timer
	///NdisMInitializeTimer(&(psSCAN->nTimer),
    ///                      Adapter->WbNdis.MiniportAdapterHandle,
    ///                      (PVOID) ScanTimerHandler,
    ///                      (PVOID) Adapter);
	OS_TIMER_INITIAL(	&(psSCAN->nTimer),
                          (PVOID) ScanTimerHandler,
                          (PVOID) Adapter);
}

void Scan_SetScanChanRange(PWB32_ADAPTER Adapter, psSCAN_REQ_PARA pScanPara)
{
	pScanPara->sChannelList.Count = psLOCAL->sSupportChanList.Count;
	OS_MEMORY_COPY( pScanPara->sChannelList.Channel,
					psLOCAL->sSupportChanList.Channel,
					psLOCAL->sSupportChanList.Count*sizeof(ChanInfo) );
}

void Scan_ResetPara(PWB32_ADAPTER Adapter)
{
	phw_data_t pHwData = &Adapter->sHwData;

	psSCAN->wState = SCAN_INACTIVE;
	psSCAN->iCurrentChannelIndex =0;
	//psSCANREQ->ScanType = PASSIVE_SCAN;
	psSCANREQ->ScanType = ACTIVE_SCAN;
	Scan_SetScanChanRange(Adapter, psSCANREQ);
	psSCANREQ->sSSID.Element_ID = ELEMENT_ID_SSID;
	psSCANREQ->sSSID.Length = 0; //broadcast SSID
	//Initial default Scan parameters, these parameters may be updated by GUI
	psSCAN->BssType = ESS_NET;
	OS_MEMORY_COPY( psSCAN->BSSID, "\xff\xff\xff\xff\xff\xff", MAC_ADDR_LENGTH ); //BSSID=broadcast;
	//psSCAN->sSSID.Element_ID = ELEMENT_ID_SSID;	//SSID=broadcast;
	//psSCAN->sSSID.Length = 0;

	psSCAN->ProbeDelay = 0;
	//psSCAN->MinChannelTime = 100;
	//psSCAN->MinChannelTime = 20;
	psSCAN->MinChannelTime = hal_scan_interval(pHwData);;

	//psSCAN->MaxChannelTime = 200;//150;
	psSCAN->MaxChannelTime = hal_scan_interval(pHwData);
	psSCAN->boBgScan = FALSE;
	psSCAN->iBgScanPeriod =0;
	psSCAN->boFastScan = FALSE;

	psSCAN->boSave = TRUE;
}

void Scan_Entry(PWB32_ADAPTER Adapter, K_MSG* psScanMsg)
{
	if (psScanMsg->wMsgType==KNLMSG_RESET)
	{	// stop Scan Timer and Scan State
		psSCAN->wState=SCAN_INACTIVE;
		vScanTimerStop(Adapter);
		return;
	}
	#ifdef _PE_STATE_DUMP_
	//WBDEBUG(("STATE: iSCAN s=%x, m=%x\n",(uint)psSCAN->wState,(uint)psScanMsg->wMsgType));
	#endif
	vKNL_StateMachine(Adapter, psScanTransTable, 
								psSCAN->wState, psScanMsg);
	#ifdef _PE_STATE_DUMP_
	//WBDEBUG(("STATE: oSCAN s=%x\n",(uint)psSCAN->wState));
	#endif
}

void SCAN_Halt(PWB32_ADAPTER Adapter)
{
	vScanTimerStop(Adapter);
	while (psSCAN->boInTimerHandler == TRUE)
	{
		///NdisMSleep(10000);//10ms
		OS_SLEEP( 10000 );//10ms
	}
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("STATE: Scan halt.\n"));
	#endif
}

void Scan_Stop(PWB32_ADAPTER Adapter)
{
	vScanTimerStop(Adapter);
}

void vScanProc_ActiveNextChannel(PWB32_ADAPTER Adapter)
{
	USHORT i;
	UCHAR	BestAntenna;

	if (psSCANREQ->ScanType == ACTIVE_SCAN)
	{
		psSCAN->iCurrentChannelIndex++;
		if (psSCAN->iCurrentChannelIndex >= psSCANREQ->sChannelList.Count)
		{
			psSCAN->wState = SCAN_COMPLETE;
			//Decide the best antenna
			if (psLOCAL->wConnectedSTAindex == 0)
			{
				if (psSCAN->RxNumPerAntenna[0] > psSCAN->RxNumPerAntenna[1])
					BestAntenna = 0;
				else
					BestAntenna = 1;
				//WBDEBUG(("Rx at Antenna 0 =%d, Rx at Antenna 1 =%d\n",
				//			psSCAN->RxNumPerAntenna[0], psSCAN->RxNumPerAntenna[1]));
				//WBDEBUG(("The best antenna is %d\n", BestAntenna));
				if( Adapter->sLocalPara.boAntennaDiversity ) // 20060613.5 Add
				{
					if (psLOCAL->bAntennaNo != BestAntenna)
					{
						psLOCAL->bAntennaNo = BestAntenna;
						hal_set_antenna_number(&Adapter->sHwData, psLOCAL->bAntennaNo);
					}
				}
			}
			//for BG-scan to return to the channel of connected STA
			//if ((i=psLOCAL->wConnectedSTAindex) != 0)
			if ((i=psSME->wDesiredJoinBSS) != 0)
			{
				ChanInfo ChanTmp;

				ChanTmp.band = psBSS(i)->band;
				ChanTmp.ChanNo = psBSS(i)->DS_Parameter_Set.Current_Channel;
				hal_set_current_channel(&Adapter->sHwData, ChanTmp);
				hal_resume_sync_bss(&Adapter->sHwData);
			}
			//hal_set_accept_beacon(&Adapter->sHwData, FALSE);
			vScanProc_Cfm(Adapter);
			if (psSCAN->boBgScan==TRUE)
			{	// Background Scan is enabled, so auto start timer.
				vScanTimerStart(Adapter, psSCAN->iBgScanPeriod);
			}
			Adapter->Mds.ScanTxPause = FALSE;
			//restart Mds_Tx frame
			Mds_Tx( Adapter );
		}
		else
		{
			#ifdef _PE_STATE_DUMP_
			WBDEBUG(("STATE: ActiveChan i=%x, band=%d, ch=%d\n",psSCAN->iCurrentChannelIndex,
					psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex].band,
					psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex].ChanNo));
			#endif
			hal_set_current_channel(&Adapter->sHwData,
						psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex]);
			vScanTimerStart(Adapter, psSCAN->ProbeDelay);
			psSCAN->wState = WAIT_PROBE_DELAY;
		}
	}
}

//return value = 0 		: fail
//				 1		: success
USHORT wRetrieveInformation(PWB32_ADAPTER Adapter, USHORT index, psRXDATA psRxFrame)
{
	USHORT ret=0;

	if (!boMLME_FoundSTAinfo(psBSS(index)))
	{
		if (wBSSaddScanData(Adapter, index, psRxFrame) == 1)
		{
			// BSS correct, change MLME-state
			MLME_findSTA(psBSS(index));
			vRateToBitmap(Adapter, index);
			ret = 1;
		}
		else
		{
			#ifdef _PE_STATE_DUMP_
			WBDEBUG(("ttt\n"));
			#endif
		}
	}
	else
	{
		wBSSUpdateScanData(Adapter, index, psRxFrame);
		ret = 1;
	}
	return ret;
}


void vScanTimerStart(PWB32_ADAPTER Adapter, int timeout_value)
{
	// NOTE: duplicate call NdisMSetTimer() will Stop old Timer and ReStart new Timer
	if (Adapter->sLocalPara.ShutDowned == FALSE)
	{
	    if (timeout_value<MIN_TIMEOUT_VAL)
			timeout_value=MIN_TIMEOUT_VAL;
		///NdisMSetTimer( &(psSCAN->nTimer), timeout_value);
		OS_TIMER_SET( &(psSCAN->nTimer), timeout_value);
	}
}

void vScanTimerStop(PWB32_ADAPTER Adapter)
{

	//psSCAN->boTimerActive = FALSE;  // can be removed
    ///NdisMCancelTimer(&psSCAN->nTimer, &boValue);
	OS_TIMER_CANCEL( &psSCAN->nTimer, &boValue );
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("STATE: scan cancel timer return valule =%x\n", boValue));
	#endif
}

//for only one argument
void ScanTimerHandler_1a(IN PVOID Data)
{
	ScanTimerHandler(NULL, (PWB32_ADAPTER)Data, NULL, NULL);
}

void ScanTimerHandler(IN PVOID			SystemSpecific1,
					  IN PWB32_ADAPTER 	Adapter,
					  IN PVOID			SystemSpecific2,
					  IN PVOID			SystemSpecific3)
{
	K_MSG sTimerMsg;

	psSCAN->boInTimerHandler = TRUE;
    sTimerMsg.wMsgType = SCANMSG_TIMEOUT;
	sTimerMsg.pMsgPtr = NULL;
	Scan_Entry(Adapter, &sTimerMsg);
	psSCAN->boInTimerHandler = FALSE;
}

//======================================================================================
//      Action Function of MLME / ESS State Transition Table 
//======================================================================================
//============================================================================
// vScanProc_ScanRequest --
//
// Description:
//   Perform scanning based on the following parameter:
//	 (1)psSCAN->bScanType
//	 (2)psSCAN->abChannelList[]
//	 (3)psSCAN->iXXXTime
//	 ??(4)psSCAN->abBSSID
//	 ??(5)psSCAN->sSSID
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//
//============================================================================
void vScanProc_ScanRequest(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	if ((psLOCAL->RadioOffStatus.boHwRadioOff == TRUE) ||
		(psLOCAL->RadioOffStatus.boSwRadioOff == TRUE))
	{
		K_MSG sSmeMsg;

		psSCAN->wState = SCAN_COMPLETE;
		hal_scan_status_indicate(&Adapter->sHwData, 0);	// complete
		sSmeMsg.wMsgType = SMEMSG_SCAN_CFM;
		sSmeMsg.wInstance = 0;
		sSmeMsg.pMsgPtr = NULL;
		SME_Entry(Adapter, &sSmeMsg);
		return;	//Radio is off, ignore this command
	}

	//update the scan request parameter
	if (psMsg->pMsgPtr != NULL)
		OS_MEMORY_COPY( psSCANREQ, psMsg->pMsgPtr, sizeof(SCAN_REQ_PARA) );

	vSimpleHouseKeeping(Adapter);
	hal_stop_sync_bss(&Adapter->sHwData);
	psSCAN->RxNumPerAntenna[0] = psSCAN->RxNumPerAntenna[1] = 0;
	psSCAN->AntennaToggle = 0;

	hal_scan_status_indicate(&Adapter->sHwData, 1);	// in progress
	FillEventLog(Adapter, EVENT_SCAN_REQ);
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("-----------STATE: START Scan--------------\n"));
	WBDEBUG(("STATE: ScanChan i=%x, band=%d, ch=%x\n",psSCAN->iCurrentChannelIndex,
				psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex].band,
				psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex].ChanNo));
	#endif
	//TODO : should psSCAN->iCurrentChannelIndex be set to 0?? Do we have to scan from
	//			the first channel every time??
	psSCAN->iCurrentChannelIndex = 0;
	hal_set_current_channel(&Adapter->sHwData, psSCANREQ->sChannelList.Channel[0]);
	if (psSCANREQ->ScanType == ACTIVE_SCAN)
	{
		Adapter->Mds.ScanTxPause = TRUE;
		//hal_set_accept_beacon(&Adapter->sHwData, TRUE);
		psSCAN->boCCAbusy = FALSE;
		// the unit of ProbeDelay is us
		vScanTimerStart(Adapter, (int)(psSCAN->ProbeDelay/1000)); 
		psSCAN->wState = WAIT_PROBE_DELAY;
	}
	else //(psSCAN->bScanType == PASSIVE_SCAN)
	{
		//hal_set_accept_beacon(&Adapter->sHwData, TRUE);
		vScanTimerStart(Adapter, psSCAN->MaxChannelTime);
		psSCAN->wState = WAIT_BEACON_MAX_PASSIVE;
	}
}

void vScanProc_ProbeDelay_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	SendProbeRequest(Adapter, &psSCANREQ->sSSID);//send fail, how??
	vScanTimerStart(Adapter, psSCAN->MinChannelTime-(int)(psSCAN->ProbeDelay/1000));
	psSCAN->wState = WAIT_RESPONSE_MIN;
}

void vScanProc_Min_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	if (psSCAN->boCCAbusy == TRUE)
	{
		vScanTimerStart(Adapter, psSCAN->MaxChannelTime-psSCAN->MinChannelTime);
		psSCAN->wState = WAIT_RESPONSE_MAX_ACTIVE;
	}
	else
	{
		if (psLOCAL->wConnectedSTAindex == 0)
		{
			if (psSCAN->AntennaToggle == 0)
			{
				//Scan second time with another antenna at the same channel
				psSCAN->AntennaToggle = 1;
				if( Adapter->sLocalPara.boAntennaDiversity ) // 20060103.1 Add
				{
					if (psLOCAL->bAntennaNo == 0)
						psLOCAL->bAntennaNo = 1;
					else
						psLOCAL->bAntennaNo = 0;

					hal_set_antenna_number(&Adapter->sHwData, psLOCAL->bAntennaNo);
				}

				vScanTimerStart(Adapter, psSCAN->ProbeDelay);
				psSCAN->wState = WAIT_PROBE_DELAY;
			}
			else
			{
				psSCAN->AntennaToggle = 0;
				vScanProc_ActiveNextChannel(Adapter);
			}
		}
		else
			vScanProc_ActiveNextChannel(Adapter);
	}
}

void vScanProc_Max_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	vScanProc_ActiveNextChannel(Adapter);
}


void vScanProc_Passive_Timeout(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	USHORT i;

	psSCAN->iCurrentChannelIndex++;
	if (psSCAN->iCurrentChannelIndex >= psSCANREQ->sChannelList.Count)
	{
		psSCAN->wState = SCAN_COMPLETE;
		//for BG-scan to return to the channel of connected STA
		if ((i=psLOCAL->wConnectedSTAindex) != 0)
		{
			ChanInfo ChanTmp;

			ChanTmp.band = psBSS(i)->band;
			ChanTmp.ChanNo = psBSS(i)->DS_Parameter_Set.Current_Channel;
			hal_set_current_channel(&Adapter->sHwData, ChanTmp);
			hal_resume_sync_bss(&Adapter->sHwData);
		}
		//hal_set_accept_beacon(&Adapter->sHwData, FALSE);
		vScanProc_Cfm(Adapter);
		if (psSCAN->boBgScan==TRUE)
		{	// Background Scan is enabled, so auto start timer.
			vScanTimerStart(Adapter, psSCAN->iBgScanPeriod);
		}
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("STATE: EndScan ch=%x\n", psBSS(i)->DS_Parameter_Set.Current_Channel));
		#endif
		Adapter->Mds.TxPause = FALSE;  // Enable Tx frame
		//restart Mds_Tx frame
		Mds_Tx( Adapter );
	}
	else
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("STATE: PassiveChan i=%x, band=%d, ch=%x\n",psSCAN->iCurrentChannelIndex,
				psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex].band,
				psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex].ChanNo));
		#endif
		hal_set_current_channel(&Adapter->sHwData,
					psSCANREQ->sChannelList.Channel[psSCAN->iCurrentChannelIndex]);
		vScanTimerStart(Adapter, psSCAN->MaxChannelTime);
		psSCAN->wState = WAIT_BEACON_MAX_PASSIVE;
	}
}

void vScanProc_StopScan(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	K_MSG sSmeMsg;

	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("-----------STATE: STOP Scan--------------\n"));
	#endif

	//hal_set_accept_beacon(&Adapter->sHwData, FALSE);
	vScanTimerStop(Adapter);
	//Adapter->Mds.TxPause = FALSE;  // Enable Tx frame
	//Adapter->Mds.ScanTxPause = FALSE;
	psSCAN->wState = SCAN_COMPLETE;
	hal_scan_status_indicate(&Adapter->sHwData, 0);	// complete
	if (psMsg->pMsgPtr != NULL)	//come from Disassoc request
	{
		sSmeMsg.wMsgType = SMEMSG_SCAN_CFM;
		sSmeMsg.wInstance = 0;
		sSmeMsg.pMsgPtr = NULL;
		SME_Entry(Adapter, &sSmeMsg);
	}
	else
	{
		Adapter->Mds.TxPause = FALSE;  // Enable Tx frame
		Adapter->Mds.ScanTxPause = FALSE;
		//restart HWMAC Tx frame
		hal_start_tx0(&Adapter->sHwData);
	}
}

void vScanProc_Cfm(PWB32_ADAPTER Adapter)
{
	K_MSG sSmeMsg;

	BssScanUpToDate(Adapter);
	hal_scan_status_indicate(&Adapter->sHwData, 0);	// complete
	sSmeMsg.wMsgType = SMEMSG_SCAN_CFM;
	sSmeMsg.wInstance = 0;
	sSmeMsg.pMsgPtr = NULL;
	SME_Entry(Adapter, &sSmeMsg);
}

void vScanProc_StartIBSSCfm(PWB32_ADAPTER Adapter, USHORT BssIdx)
{
	K_MSG sSmeMsg;

	sSmeMsg.wMsgType = SMEMSG_START_IBSS_CFM;
	sSmeMsg.wInstance = BssIdx;
	sSmeMsg.pMsgPtr = NULL;
	SME_Entry(Adapter, &sSmeMsg);
}

void vScanProc_RcvProbeRsp(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	#ifdef _PE_RX_DUMP_
	WBDEBUG(("RX: rcv probe response\n"));
	#endif
	psSCAN->RxNumPerAntenna[psLOCAL->bAntennaNo]++;
	wRetrieveInformation(Adapter, psMsg->wInstance, (psRXDATA)psMsg->pMsgPtr);

	StartIbssCheck(Adapter, psMsg->wInstance);
}

//============================================================================
// vScanProc_RcvBeacon --
//
// Description:
//		Analyze the received beacon frames and determine whether the IBSS has been
//	established successfully if 
//	
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//
//============================================================================
void vScanProc_RcvBeacon(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	USHORT wBssIdx;
	//ULONG	dwData;
	//UCHAR	BSSID[MAC_ADDR_LENGTH];
	phw_data_t	pHwData = &Adapter->sHwData;

	#ifdef _PE_RX_DUMP_
	//WBDEBUG(("RX: rcv beacon\n"));
	#endif
	psSCAN->RxNumPerAntenna[psLOCAL->bAntennaNo]++;
	wBssIdx = psMsg->wInstance;
	if (!wRetrieveInformation(Adapter, wBssIdx, (psRXDATA)psMsg->pMsgPtr))
		return;

	// IBSS case
	//if (wBssIdx == 0)	//If wBssIdx == 0, it means the BssDescriptor has existed.
	//	return;	//One case: In WHQL test, the BssDescriptor of the peer STA may has existed
				//			due to the former test items and then the start IBSS will fail
				//			in this test item.

	if	((psSME->wDesiredJoinBSS != 0) &&
		 (psBSS(psSME->wDesiredJoinBSS)->bBssType == IBSS_NET))
	{
		if ((psLOCAL->wConnectedSTAindex == 0) &&
			 (psBSS(wBssIdx)->bBssType == IBSS_NET))
		{
			hal_get_bssid(&Adapter->sHwData, psLOCAL->HwBssid);
			if (psLOCAL->HwBssidValid == TRUE)
			{
				if( boCmpMacAddr( psLOCAL->HwBssid, psBSS(wBssIdx)->abBssID ) )
				{
					#ifdef _PE_STATE_DUMP_
					WBDEBUG(("** Got the H/W BSSID and start confirm. **\n"));
					WBDEBUG(("Peer Bss index =%x\n", wBssIdx));
					WBDEBUG(("read BSSID=%x-%x-%x-%x-%x-%x\n",
								psLOCAL->HwBssid[0],psLOCAL->HwBssid[1],psLOCAL->HwBssid[2],
								psLOCAL->HwBssid[3],psLOCAL->HwBssid[4],psLOCAL->HwBssid[5]));
					//WBDEBUG(("Dump partial of this beacon\n"));
					//mac_dump_data(psMsg->pMsgPtr->pbFramePtr, 40, 0);
					#endif

					//Only for Start IBSS and waiting for a beacon from other STA joined in this IBSS. 
					// if (psBSS(wBssIdx)->wState<IBSS_JOIN_SYNC)  JoinCfm to MLMEtask
		    		// get other STA in same IBSS, but keep its MLMEstate at {IDLE_SCAN}
					//  MLME_JoinCfm(psBSS(wBssIdx), psBSS(wBssIdx)->bBssType);
		 			// The state of this BSSdescription will not be changed, only
					// psBSS(wBssIdx) will be changed to IBSS_JOIN_SYNC
					//hal_set_accept_beacon(&Adapter->sHwData, FALSE);
					if (pHwData->IsWaitJoinComplete)
					{
						pHwData->IsWaitJoinComplete = FALSE;
						hal_join_OK( pHwData );
					}
					else
						vScanProc_StartIBSSCfm(Adapter, wBssIdx);
				}
			}
		}
	}
}

void StartIbssCheck(PWB32_ADAPTER Adapter, USHORT wBssIdx)
{
	K_MSG sSmeMsg;

	if	((psSME->wDesiredJoinBSS != 0) &&
		 (psBSS(psSME->wDesiredJoinBSS)->bBssType == IBSS_NET))
	{
		if ((psLOCAL->wConnectedSTAindex == 0) &&
			 (psBSS(wBssIdx)->bBssType == IBSS_NET))
		{
			//rejoin
			if (  (boCmpSSID(&psBSS(wBssIdx)->SSID, &psBSS(psSME->wDesiredJoinBSS)->SSID)) &&
			 ( ( (psBSS(wBssIdx)->band != psBSS(psSME->wDesiredJoinBSS)->band) ||    (psBSS(wBssIdx)->DS_Parameter_Set.Current_Channel != psBSS(psSME->wDesiredJoinBSS)->DS_Parameter_Set.Current_Channel))))  
			{
				sSmeMsg.wMsgType = SMEMSG_JOIN_REQ;
				sSmeMsg.wInstance = wBssIdx;
				sSmeMsg.pMsgPtr = NULL;
				SME_Entry(Adapter, &sSmeMsg);
			}
		}
	}

}

void vStart_BgScanTimer(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	// start Background scan timer, WinXP: every 5 sec scan once, period scan
	vScanTimerStart(Adapter, psSCAN->iBgScanPeriod);
	psSCAN->boBgScan=TRUE;
}

//============================================================================
// vStart_BgScan --
//
// Description:
//		Hanlde the SCAN_REQ at SCAN_COMPLETE state
//
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//
//============================================================================
void vStart_BgScan(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	if ((psLOCAL->RadioOffStatus.boHwRadioOff == TRUE) ||
		(psLOCAL->RadioOffStatus.boSwRadioOff == TRUE))
		return;	//Radio is off, ignore this command

	//update the scan request parameter
	if (psMsg->pMsgPtr != NULL)
		OS_MEMORY_COPY( psSCANREQ, psMsg->pMsgPtr, sizeof(SCAN_REQ_PARA) );

	//-------------------------------------------------
	if (psSME->bDesiredPowerSave)
	{
		if ((psLOCAL->wConnectedSTAindex == 0) ||
				((psLOCAL->wConnectedSTAindex != 0) &&
								 (psBSS(psLOCAL->wConnectedSTAindex)->bBssType == ESS_NET)))
		{
			K_MSG	sSmeMsg;
			UCHAR		PsMode;

			//wake up the H/W
			PsMode =  PWR_ACTIVE;
			sSmeMsg.wMsgType = SMEMSG_POWERSAVE_REQ;
			sSmeMsg.pMsgPtr = &PsMode;
			SME_Entry(Adapter, &sSmeMsg);
		}
	}

	hal_scan_status_indicate(&Adapter->sHwData, 1);	// in progress
	FillEventLog(Adapter, EVENT_SCAN_REQ);
	vSimpleHouseKeeping(Adapter);
	hal_stop_sync_bss(&Adapter->sHwData);
	psSCAN->RxNumPerAntenna[0] = psSCAN->RxNumPerAntenna[1] = 0;
	psSCAN->AntennaToggle = 0;
	hal_set_current_channel(&Adapter->sHwData, psSCANREQ->sChannelList.Channel[0]);
	psSCAN->iCurrentChannelIndex = 0;
	if (psSCANREQ->ScanType == ACTIVE_SCAN)
	{
		K_MSG sTimerMsg;

		Adapter->Mds.ScanTxPause = TRUE;
		//hal_stop_sync_bss(&Adapter->sHwData);
		psSCAN->boCCAbusy = FALSE;
		// the unit of ProbeDelay is us
		//vScanTimerStart(Adapter, (int)(psSCAN->ProbeDelay/1000)); 
		psSCAN->wState = WAIT_PROBE_DELAY;



	    sTimerMsg.wMsgType = SCANMSG_TIMEOUT;
		sTimerMsg.pMsgPtr = NULL;
		Scan_Entry(Adapter, &sTimerMsg);

	}
	else //(psSCAN->bScanType == PASSIVE_SCAN)
	{	// NOTE: complete BG-Scan, should tune Chan to CONNECTED Chan
		Adapter->Mds.TxPause = TRUE; // Start BG scan,stop Tx
		//hal_set_accept_beacon(&Adapter->sHwData, TRUE);
		vScanTimerStart(Adapter, psSCAN->MaxChannelTime);
		psSCAN->wState = WAIT_BEACON_MAX_PASSIVE;
	}
}

/*
void vScanProc_TxProbeFail(PWB32_ADAPTER Adapter, K_MSG* psMsg)
{
	if (psSCANREQ->ScanType == ACTIVE_SCAN)
	{
		vScanTimerStart(Adapter, (int)(psSCAN->ProbeDelay/1000));
		psSCAN->wState = WAIT_PROBE_DELAY;
	}
}
*/
